package com.yungu.swift.order.utils;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.order.config.NacosListener;
import com.yungu.swift.order.model.vo.RefundVo;
import com.yungu.swift.system.finance.model.dto.FinanceJoinRefundDto;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.Md5Utils;
import com.yungu.swift.utils.StringUtils;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Component
public class RefundDataBuilder {

    /**
     * 微信退款数据构建
     *
     * @param refundVo
     * @return
     */
    public static ResponseData<String> buildWxRefundData(RefundVo refundVo) {
        Map<String, String> map = new HashMap<>();
        //--以下为必填参数
        //公众账号ID
        map.put("appid", NacosListener.WXPAY_CONFIG.getPassengerWxAppid());
        //商户号
        map.put("mch_id", NacosListener.WXPAY_CONFIG.getPassengerWxPartner());
        //随机字符串
        map.put("nonce_str", buildNonceStr());
        //商户订单号
        map.put("out_trade_no", refundVo.getPayTradeNo());
        //商户退款单号
        map.put("out_refund_no", refundVo.getTradeNo());
        Double actualFare = refundVo.getActualFare() * 100;
        Double refundFare = refundVo.getRefundFare() * 100;
        //标价金额(以分为单位)
        map.put("total_fee", String.valueOf(actualFare.intValue()));
        //标价金额(以分为单位)
        map.put("refund_fee", String.valueOf(refundFare.intValue()));

        //签名
        String sign = PaySignBuilder.wxSignMD5(map, NacosListener.WXPAY_CONFIG.getPassengerWxAppKey());
        if (StringUtils.isEmpty(sign)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "参数MD5签名失败");
        }
        map.put("sign", sign);
        String refundXml = XmlUtils.buildXml(map);
        Map<String, String> resultMap;
        try {
            InputStream certPath = RefundDataBuilder.class.getResourceAsStream("/apiclient_cert.p12");
            String resultStr = TenpayHttpClient.doSslRequest("https://api.mch.weixin.qq.com/secapi/pay/refund",
                    refundXml, NacosListener.WXPAY_CONFIG.getPassengerWxPartner(), certPath);
            resultMap = XmlUtils.readValueAsMap(resultStr);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信XML解析异常");
        }
        if (resultMap == null || resultMap.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信XML返回值为空");
        }
        if (!"SUCCESS".equals(resultMap.get("return_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信退款通讯异常 -- " + resultMap.get("return_msg"));
        }
        if (!"SUCCESS".equals(resultMap.get("result_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信创建退款异常 -- " + resultMap.get("err_code_des"));
        }
        return ResponseData.buildSuccessResponse("微信退款成功", resultMap.get("refund_id"));
    }


    /**
     * 支付宝退款查询数据构建
     *
     * @param refundVo
     * @return
     */
    public static ResponseData<String> buildAliRefundData(RefundVo refundVo) {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                NacosListener.ALIPAY_CONFIG.getOpenAppid(),
                NacosListener.ALIPAY_CONFIG.getOpenBizPrivateKey(),
                "JSON", "UTF-8",
                NacosListener.ALIPAY_CONFIG.getOpenBizPublicKey(), "RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        Map<String, Object> bizContent = MapUtils.build();
        bizContent.put("out_trade_no", refundVo.getPayTradeNo());
        DecimalFormat df = new DecimalFormat("#.00");
        bizContent.put("refund_amount", Double.parseDouble(df.format(refundVo.getRefundFare())));
        try {
            request.setBizContent(JsonUtils.writeJsonStr(bizContent));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        AlipayTradeRefundResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (null != response && response.isSuccess()) {
            return ResponseData.buildSuccessResponse("支付宝退款成功", response.getTradeNo());
        } else {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "支付宝退款失败");
        }
    }


    /**
     * 微信退款查询数据构建
     *
     * @param financeJoinRefundDto
     * @return
     */
    public static ResponseData<Boolean> buildWxRefundQueryData(FinanceJoinRefundDto financeJoinRefundDto) {
        Map<String, String> map = new HashMap<>();
        //--以下为必填参数
        //公众账号ID
        map.put("appid", NacosListener.WXPAY_CONFIG.getPassengerWxAppid());
        //商户号
        map.put("mch_id", NacosListener.WXPAY_CONFIG.getPassengerWxPartner());
        //随机字符串
        map.put("nonce_str", buildNonceStr());
        //商户退款单号
        map.put("refund_id", financeJoinRefundDto.getRefundNo());

        //签名
        String sign = PaySignBuilder.wxSignMD5(map, NacosListener.WXPAY_CONFIG.getPassengerWxAppKey());
        if (StringUtils.isEmpty(sign)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "参数MD5签名失败");
        }
        map.put("sign", sign);
        String refundXml = XmlUtils.buildXml(map);

        //微信需要http通讯请求预支付信息
        TenpayHttpClient httpClient = new TenpayHttpClient();
        String resultStr;
        Map<String, String> resultMap = new HashMap<String, String>();
        if (httpClient.callHttpPost("https://api.mch.weixin.qq.com/pay/refundquery", refundXml)) {
            try {
                resultStr = httpClient.getResContent();
                resultMap = XmlUtils.readValueAsMap(resultStr);
            } catch (Exception e) {
                e.printStackTrace();
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信XML解析异常");
            }
        }
        if (resultMap == null || resultMap.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信XML返回值为空");
        }
        if (!"SUCCESS".equals(resultMap.get("return_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信退款查询通讯异常 -- " + resultMap.get("return_msg"));
        }
        if (!"SUCCESS".equals(resultMap.get("result_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信查询退款异常 -- " + resultMap.get("err_code_des"));
        }
        if (resultMap.containsKey("refund_status_0")) {
            if ("SUCCESS".equals(resultMap.get("refund_status_0"))) {
                return ResponseData.buildSuccessResponse("微信退款查询成功", true);
            }
        }
        return ResponseData.buildSuccessResponse("微信退款查询成功", false);
    }


    /**
     * 支付宝退款查询数据构建
     *
     * @param financeJoinRefundDto
     * @return
     */
    public static ResponseData<Boolean> buildAliRefundQueryData(FinanceJoinRefundDto financeJoinRefundDto) {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                NacosListener.ALIPAY_CONFIG.getOpenAppid(),
                NacosListener.ALIPAY_CONFIG.getOpenBizPrivateKey(), "JSON", "UTF-8",
                NacosListener.ALIPAY_CONFIG.getOpenBizPublicKey(), "RSA2");
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_request_no", financeJoinRefundDto.getPayTradeNo());
        bizContent.put("trade_no", financeJoinRefundDto.getRefundNo());
        request.setBizContent(JsonUtils.toJSONString(bizContent));
        AlipayTradeFastpayRefundQueryResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (response.isSuccess()) {
            if (StringUtils.isNotBlank(response.getTradeNo())) {
                return ResponseData.buildSuccessResponse("支付宝退款查询成功", true);
            }
            return ResponseData.buildSuccessResponse("支付宝退款查询成功", false);
        } else {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "支付宝退款查询失败");
        }
    }

    public static String buildNonceStr() {
        return Md5Utils.encode(String.valueOf(new Random().nextInt(10000)));
    }

}
